package com.quectel.cms.controller.alarm;


import cn.hutool.core.collection.CollectionUtil;
import com.google.common.base.Preconditions;
import com.quectel.cms.controller.BaseController;
import com.quectel.cms.util.SessionHolder;
import com.quectel.util.aspect.log.annotation.Log;
import com.quectel.constant.global.annotation.RequirePermissions;
import com.quectel.constant.global.annotation.RequireTenants;
import com.quectel.constant.sys.SysConstants;
import com.quectel.core.module.alarm.dto.AlarmRuleConditionDto;
import com.quectel.core.module.alarm.dto.AlarmRuleDto;
import com.quectel.core.module.alarm.dto.AlarmRuleTenantConditionDto;
import com.quectel.core.module.alarm.service.AlarmRuleConditionService;
import com.quectel.core.module.alarm.service.AlarmRuleDeviceConditionService;
import com.quectel.core.module.alarm.service.AlarmRuleService;
import com.quectel.core.module.alarm.service.AlarmRuleTenantConditionService;
import com.quectel.core.module.device.dto.DeviceColumnDto;
import com.quectel.core.module.device.dto.DeviceDto;
import com.quectel.core.module.device.service.DeviceCategoryService;
import com.quectel.core.module.device.service.DeviceColumnService;
import com.quectel.core.module.device.service.DeviceService;
import com.quectel.core.module.device.service.DeviceTypeService;
import com.quectel.util.common.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/**
 * @author caolu
 * @email louis.cao@quectel.com
 * @date 2019-05-31 12:25:26
 */
@RestController
@RequestMapping("alarmRule")
@Tag(name = "AlarmRuleController", description = "告警规则相关api")
public class AlarmRuleController extends BaseController {

    @DubboReference
    private AlarmRuleService alarmRuleService;
    @DubboReference
    private DeviceCategoryService deviceCategoryService;
    @DubboReference
    private DeviceColumnService deviceColumnService;
    @DubboReference
    private DeviceTypeService deviceTypeService;
    @DubboReference
    private AlarmRuleConditionService alarmRuleConditionService;
    @DubboReference
    private AlarmRuleTenantConditionService alarmRuleTenantConditionService;
    @DubboReference
    private AlarmRuleDeviceConditionService alarmRuleDeviceConditionService;
    @DubboReference
    private DeviceService deviceService;

    /**
     * 查询所有规则
     */
    @GetMapping("listAll")
    @RequirePermissions(values = "alarmRule:list")
    @Operation(summary = "告警规则的查询列表")
    public Response<List<AlarmRuleDto>> listAll(@RequestParam Map<String, Object> params) {

        super.fillAuthorityData(params);

        List<AlarmRuleDto> list = alarmRuleService.queryAll(params);

        return Response.<List<AlarmRuleDto>>ok().wrap(list);
    }

    /**
     * 列表
     */
    @GetMapping("list")
    @RequirePermissions(values = "alarmRule:list")
    @Operation(summary = "告警规则的分页查询列表")
    public Response<Page<AlarmRuleDto>> list(@RequestParam Map<String, Object> params) {
        //查询列表数据
        Request request = Request.configParams(params);

        super.fillAuthorityData(params);

        List<AlarmRuleDto> list = alarmRuleService.queryList(params);
        if (CollectionUtil.isNotEmpty(list)) {
            for (AlarmRuleDto alarmRuleDto : list) {
                paddingRealRule(alarmRuleDto);
            }
        }
        int total = alarmRuleService.queryTotal(params);

        Page<AlarmRuleDto> page = new Page<>(request.getPageNo(), request.getPageSize(), total, list);
        return Response.<Page<AlarmRuleDto>>ok().wrap(page);
    }

    /**
     * 列表
     */
    @GetMapping("queryRuleByDeviceId")
    @Operation(summary = "通过设备id查询对应的告警规则列表")
    public Response<List<AlarmRuleDto>> queryRuleByDeviceId(@RequestParam Long deviceId) {
        DeviceDto deviceDto = deviceService.selectById(deviceId);
        Preconditions.checkArgument(deviceDto != null);
        List<AlarmRuleDto> alarmRuleByDevice = alarmRuleService.getAlarmRuleByDevice(deviceDto);
        return Response.<List<AlarmRuleDto>>ok().wrap(alarmRuleByDevice);
    }

    /**
     * 列表
     */
    @GetMapping("queryRuleByDeviceTypeId")
    @Operation(summary = "通过设备类型id,查询对应的告警规则列表")
    public Response<List<AlarmRuleDto>> queryRuleByDeviceTypeId(@RequestParam Long deviceTypeId) {
        return Response.<List<AlarmRuleDto>>ok().wrap(alarmRuleService.getAlarmRuleByDeviceTypeId(SessionHolder.getSysUser().getTenantId(), deviceTypeId));
    }


    /**
     * 信息
     */
    @GetMapping("info/{id}")
    @RequirePermissions(values = "alarmRule:info")
    @Operation(summary = "查询单条告警规则记录")
    public Response<AlarmRuleDto> info(@PathVariable("id") Long id) {

        AlarmRuleDto alarmRuleDto = alarmRuleService.selectById(id);
        paddingRealRule(alarmRuleDto);
        return Response.<AlarmRuleDto>ok().wrap(alarmRuleDto);
    }

    private void paddingRealRule(AlarmRuleDto alarmRuleDto) {
        if (!SysConstants.SYS_TOP_TENANT_CODE.equals(SessionHolder.getSysUser().getTenantCode())) {
            //不是超级租户 需要查看其他租户的设置情况
            AlarmRuleTenantConditionDto alarmRuleTenantConditionDto =
                    alarmRuleTenantConditionService.selectByTenantIdAndRuleId(
                            SessionHolder.getSysUser().getTenantId(),
                            alarmRuleDto.getId()
                    );
            if (alarmRuleTenantConditionDto != null) {
                AlarmRuleDto tenantRule =
                        JacksonUtils.parse(alarmRuleTenantConditionDto.getAlarmRuleConditionJson(), AlarmRuleDto.class);

                alarmRuleDto.setLevel(tenantRule.getLevel());
                alarmRuleDto.setStatus(tenantRule.getStatus());
                alarmRuleDto.setName(tenantRule.getName());
                alarmRuleDto.setAlarmConditionList(tenantRule.getAlarmConditionList());
            }
        }
    }

    /**
     * 只有超级组可以新增规则
     */
    @PostMapping("save")
    @RequirePermissions(values = "alarmRule:edit")
    @RequireTenants(values = SysConstants.SYS_TOP_TENANT_CODE)
    @Operation(summary = "新增单条告警规则")
    @Log(express = "新增告警规则")
    public Response<Object> save(@RequestBody @Validated AlarmRuleDto alarmRuleDto) {

        AlarmRuleDto dbValue = alarmRuleService.selectByCode(alarmRuleDto.getCode());
        if (dbValue != null) {
            return Response.error("告警规则编码已被占用");
        }

        if (alarmRuleDto.getAlarmConditionList() != null) {
            alarmRuleDto.getAlarmConditionList().forEach(v -> v.setCondition(HtmlUtils.decode(v.getCondition())));
        }

        //填充基础数据
        fillSaveCommonData(alarmRuleDto);

        if (alarmRuleDto != null && alarmRuleDto.getAlarmConditionList() != null) {
            //填充column信息
            for (AlarmRuleConditionDto alarmRuleConditionDto : alarmRuleDto.getAlarmConditionList()) {
                Long deviceColumnId = alarmRuleConditionDto.getDeviceColumnId();
                if (deviceColumnId != null) {
                    DeviceColumnDto deviceColumnDto = deviceColumnService.selectById(deviceColumnId);
                    if (deviceColumnDto != null) {
                        alarmRuleConditionDto.setDeviceColumnEntityName(deviceColumnDto.getEntityName());
                        alarmRuleConditionDto.setDeviceColumnCnName(deviceColumnDto.getCnName());
                    }
                }
            }
        }

        alarmRuleService.save(alarmRuleDto);

        return Response.ok();
    }

    /**
     * 修改
     */
    @PostMapping("update")
    @RequirePermissions(values = "alarmRule:edit")
    @Operation(summary = "编辑单条告警规则")
    @Log(express = "编辑告警规则")
    public Response<Object> update(@RequestBody @Validated AlarmRuleDto alarmRuleDto) {

        if (alarmRuleDto.getAlarmConditionList() != null) {
            alarmRuleDto.getAlarmConditionList().forEach(v -> v.setCondition(HtmlUtils.decode(v.getCondition())));
        }

        //填充基础数据
        fillEditCommonData(alarmRuleDto);

        if (alarmRuleDto != null && alarmRuleDto.getAlarmConditionList() != null) {
            for (AlarmRuleConditionDto alarmRuleConditionDto : alarmRuleDto.getAlarmConditionList()) {
                Long deviceColumnId = alarmRuleConditionDto.getDeviceColumnId();
                if (deviceColumnId != null) {
                    DeviceColumnDto deviceColumnDto = deviceColumnService.selectById(deviceColumnId);
                    if (deviceColumnDto != null) {
                        alarmRuleConditionDto.setDeviceColumnEntityName(deviceColumnDto.getEntityName());
                        alarmRuleConditionDto.setDeviceColumnCnName(deviceColumnDto.getCnName());
                    }
                }
            }
            if (SysConstants.SYS_TOP_TENANT_CODE.equals(SessionHolder.getSysUser().getTenantCode())) {
                //如果是超级租户则直接编辑即可
                //填充column信息
                alarmRuleService.updateById(alarmRuleDto);
            } else {
                //其他租户
                AlarmRuleDto dbValue = alarmRuleService.selectById(alarmRuleDto.getId());
                //以下为其他租户可以修改的地方
                dbValue.setLevel(alarmRuleDto.getLevel());
                dbValue.setStatus(alarmRuleDto.getStatus());
                dbValue.setName(alarmRuleDto.getName());
                dbValue.setAlarmConditionList(alarmRuleDto.getAlarmConditionList());
                AlarmRuleTenantConditionDto alarmRuleTenantConditionDto = new AlarmRuleTenantConditionDto();
                alarmRuleTenantConditionDto.setTenantId(SessionHolder.getSysUser().getTenantId());
                alarmRuleTenantConditionDto.setRuleId(dbValue.getId());
                alarmRuleTenantConditionDto.setAlarmRuleConditionJson(JacksonUtils.toJsonString(dbValue));
                alarmRuleTenantConditionService.saveOrUpdate(alarmRuleTenantConditionDto);
            }
        }
        return Response.ok();
    }

    /**
     * 删除
     */
    @PostMapping("delete")
    @RequirePermissions(values = "alarmRule:delete")
    @Operation(summary = "批量删除存在的告警规则")
    @RequireTenants(values = SysConstants.SYS_TOP_TENANT_CODE)
    public Response<Object> delete(@RequestBody Long[] ids) {

        alarmRuleService.deleteBatch(ids);

        return Response.ok();
    }

}
